home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!cs.odu.edu!Amiga-Request
- From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
- Newsgroups: comp.sources.amiga
- Subject: v90i133: ls 3.1 - UNIX-like ls utility, Part03/03
- Message-ID: <12130@xanth.cs.odu.edu>
- Date: 10 Apr 90 21:27:17 GMT
- Sender: tadguy@cs.odu.edu
- Reply-To: kim@uts.amdahl.com (Kim E. DeVaughn)
- Lines: 1470
- Approved: tadguy@cs.odu.edu (Tad Guy)
- X-Mail-Submissions-To: Amiga@cs.odu.edu
- X-Post-Discussions-To: comp.sys.amiga
-
- Submitted-by: kim@uts.amdahl.com (Kim E. DeVaughn)
- Posting-number: Volume 90, Issue 133
- Archive-name: unix/ls-3.1/part03
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 3)."
- # Contents: src/ls.c
- # Wrapped by tadguy@xanth on Tue Apr 10 17:22:51 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'src/ls.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/ls.c'\"
- else
- echo shar: Extracting \"'src/ls.c'\" \(43452 characters\)
- sed "s/^X//" >'src/ls.c' <<'END_OF_FILE'
- X/* ---------------------------------------------------------------------
- X LS.C -- Source code for the "improved" directory utility.
- X
- X Author: Justin V. McCormick
- X
- X V1.0 August 1986 Written from scratch, my first Amiga project.
- X V2.0 November 1988 Revised for Lattice 5.0 and made 1.3 compatible.
- X V2.1 December 1988 Minor size reduction, fixed a few bugs from 2.0.
- X V2.2 December 1988 Fixed status return and multiple wildcard pathnames.
- X V3.0 July 25, 1989 Instant sorting, best-fit output, new features.
- X V3.1 July 29, 1989 Bug fixes, new output width and height options.
- X
- XNotice:
- X
- X This program is placed in the public domain with the
- Xunderstanding that the author makes no claims or guarantees with
- Xregard to its suitability for any given application, and that
- Xthe author assumes no responsibility for damages incurred by its
- Xusage. Any resemblance of this program to any other program,
- Xeither living or dead, is purely coincidental.
- X
- X Feel free to borrow this code and make millions of dollars
- Xfrom its sale or commercial use, but please give credit where
- Xcredit is due.
- X
- XSynopsis:
- X
- X Features intelligent columnar listing, versatile sort options,
- XUNIX-style pattern matching, recursive subdirectory listing, and
- Xmore!
- X
- XUsage:
- X LS [options] [pattern1] [pattern2] ...
- X
- XBugs and Limitations:
- X
- X LS cannot pattern match devices (like "dh*:"), since this
- Xwould involve another level of recursion and parsing the Device
- XList. LS shows signs of the same "creeping featurism" which
- Xafflicted the UNIX command, evident from its bloated code size.
- X
- XChanges From 1.0 to 2.0:
- X
- X o Source code prototyped, linted, traced, optimized, tweaked, etc.
- X o Made resident ("pseudo-pure") by linking with cres.o from LC 5.0.
- X o High-volume routines recoded in assembly (lssup.a).
- X o Now handles multiple paths/files on a command line, up to 30.
- X o New sort flags, including no sort.
- X o Enhanced wildcards, understands complex *.?*.* expressions now.
- X o More efficient ExNext() performance, less ram used for recursion.
- X o SIGBREAKF_CTRL_C signal (Ctrl-C) cleanly aborts at any point now.
- X o Command line parser handles quoted pathnames now (LC 5.0 benefit).
- X o Short listing finally auto-adjusts to new console window sizes!
- X o Pen color escape codes bypassed when redirecting long output.
- X o Sorting by size or date is also subsorted alphabetically now.
- X o Long listing shows new 1.3 file attributes, plus comment indicator.
- X o File dates are now in international format, YY-MM-DD.
- X o Fixed listings with files datestamped after 99-12-31 (overflow).
- X o Fixed listings with files datestamped before 78-01-01 (time < 0).
- X
- XChanges From 2.0 to 2.1
- X
- X o Fixed the show comment feature, a last minute bug in 2.0.
- X o Fixed the "Unknown option ''" message problem.
- X o Optimized the assembly branches, reduced code size another few bytes.
- X
- XChanges From 2.1 to 2.2
- X
- X o Fixed erroneous Status returns.
- X o Fixed bug with multiple wildcarded pathnames.
- X o Compiled with LC 5.0 Patch 3 and CAPE 2.0, saved another 46 bytes.
- X o Eliminated an extra stpcpy(), saved another few bytes.
- X
- XChanges From 2.2 to 3.0
- X
- X o Added many new command line options! See Usage descriptions and docs.
- X o "Instant" output sorting, now using an on-the-fly insertion sort.
- X o New Short listing technique is row-by-row, redirects to PRT: or file.
- X o Better columnization of short listings, uses best-fit optimization.
- X o Formatted output parsing system implemented for long listings.
- X o Improved ^C handling, now breaks immediately in mid-output.
- X o New command line parser, now handles multiple options mixed with names.
- X o Added separate pattern matching for directories and files.
- X o Now inhibits system requesters from popping up by default.
- X o Added custom cres.o module for more size savings.
- X o Now uses Exec List functions for smaller, faster code.
- X o Fixed random cli_ReturnCode and pr_Result2 value CLI returns.
- X o Rewrote many sections, further code cleaning/commenting.
- X o Eliminated main(), LS handles the _main() function for smaller code.
- X o Compiled with 5.03.90 (beta) Lattice compiler, saved a few bytes.
- X
- XChanges From 3.0 to 3.1
- X o Fixed random errors from uninitialized argument count in GetCLIArgs().
- X o New -X and -Y options to specify short format columns and rows.
- X
- X --------------------------------------------------------------------- */
- X
- X/* ---------------------- LS SOURCE ---------------------------------- */
- X
- X/* Use Real strlen unless you comment out the following */
- X#define strlen strlen
- X
- X/* Maximum number of command line arguments */
- X#define MAXARG 32
- X#define PADTABSIZE 100
- X#define WORKSIZE 300
- X
- X#include "WORK:ls.h"
- X
- X/* Extern CODE from lssup.a */
- Xextern BYTE *aindex __ARGS((BYTE *, BYTE));
- Xextern LONG __stdargs asprintf __ARGS((BYTE *, BYTE *,...));
- Xextern LONG CompareDateStamps __ARGS((struct DateStamp *, struct DateStamp *));
- Xextern LONG CompFibs __ARGS((LONG, struct FileInfoBlock *, struct FileInfoBlock *));
- Xextern LONG FillFibEntry __ARGS((struct List *, struct FileInfoBlock *));
- Xextern LONG GetFileString __ARGS((BYTE *, BYTE *));
- Xextern LONG GetPathString __ARGS((BYTE *, BYTE *));
- Xextern LONG iswild __ARGS((BYTE *));
- Xextern LONG wildmatch __ARGS((BYTE *, BYTE *));
- Xextern VOID *myalloc __ARGS((LONG));
- Xextern VOID FibFileDate __ARGS((struct DateStamp *, BYTE *, BYTE *));
- Xextern VOID GetWinBounds __ARGS((LONG *, LONG *));
- Xextern VOID InsertFibNode __ARGS((struct List *, struct FibEntry *));
- Xextern VOID MakePathString __ARGS((struct FileLock *, BYTE *));
- Xextern VOID myfree __ARGS((VOID *));
- Xextern VOID NoFileExit __ARGS((BYTE *));
- Xextern VOID NoMemExit __ARGS((VOID));
- X
- X/* Local DATA */
- Xstruct DateStamp theolddate; /* Show files older than this date */
- Xstruct DateStamp thenewdate; /* Show files newer than this date */
- Xstruct FileHandle *ConOut; /* Standard output */
- Xstruct FileHandle *ConIn; /* Standard input */
- Xstruct FileLock *CurFLock; /* Global Directory lock */
- Xstruct FileInfoBlock *GFibp; /* Global FIB for Examine/ExNext */
- XAPTR OldWindowPtr; /* Copy of what was in pr_WindowPtr */
- X
- X/* User flags, See ls.h for bit definitions */
- XULONG LSFlags = SHOWDIRS | SHOWFILES;
- X
- XLONG gdircount; /* Grand total # of dirs for Recursive */
- XLONG gfilecount; /* Grand total # of files found */
- XLONG gtotblocks; /* Grand total # of blocks */
- XLONG gtotbytes; /* Grand total # of bytes */
- X
- XLONG dircount; /* Number of directories found */
- XLONG filecount; /* Number of files found */
- XLONG totblocks; /* total # of blocks */
- XLONG totbytes; /* total # of bytes */
- XLONG maxnamlen; /* Longest name found */
- XLONG sortkey; /* 0=alpha, 1=size, 2=date */
- X
- XBYTE padtab[PADTABSIZE]; /* Column table tab amounts */
- XBYTE thePath[WORKSIZE]; /* Current filename space */
- XBYTE theDirPat[WORKSIZE]; /* Dirname pattern workspace */
- XBYTE theFilePat[WORKSIZE]; /* Filename pattern workspace */
- XBYTE workstr[WORKSIZE+64]; /* Temp string space */
- X
- XBYTE theblksstr[20];
- XBYTE thedatestr[12];
- XBYTE theprotstr[12];
- XBYTE thesizestr[20];
- XBYTE thetimestr[12];
- X
- XLONG CurWinRows; /* Window bounds, determined at runtime */
- XLONG CurWinCols;
- X
- X/* Initialized Strings */
- XBYTE Author[] = "\23333mLS 3.1\2330m PD Freeware by Justin V. McCormick 89-07-29";
- XBYTE usage[] = "\n Usage: LS [-options <args>] [path1] [path2] ...\n";
- XBYTE usage0[] = "\tc Show filenotes D Show dirs last\n";
- XBYTE usage1[] = "\td Dirs only H No headings and subtotals\n";
- XBYTE usage2[] = "\tf Files only I No page prompts\n";
- XBYTE usage3[] = "\tk No ANSI display codes M Mixed output files and dirs\n";
- XBYTE usage4[] = "\tl Long listing N <name> Show newer than entry\n";
- XBYTE usage5[] = "\tn No sort O <name> Show older than entry\n";
- XBYTE usage6[] = "\tp Permit system requests P Show full pathnames\n";
- XBYTE usage7[] = "\tr Reverse sort R Recursive listing\n";
- XBYTE usage8[] = "\ts Sort by size T Total all subtotals\n";
- XBYTE usage9[] = "\tt Sort by date X <wide> Set output columns\n";
- XBYTE usage10[] = "\tv <pattern> Avoid pattern Y <high> Set output rows\n";
- XBYTE usage11[] = "\tF <format> Format output (default: \042";
- XBYTE usage12[] = "\042)\n";
- X
- X/* Date and output format strings */
- XBYTE baddatestr[] = "00-00-00";
- XBYTE badtimestr[] = "00:00:00";
- XBYTE datepat[] = "%02ld-%02ld-%02ld";
- XBYTE timepat[] = "%02ld:%02ld:%02ld";
- XBYTE dayspermonth[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
- XBYTE deffmtstr[40] = "%p %d %t %4b %8s %n\\n";
- XBYTE LongFmtStr[] = "%ld";
- XBYTE totalfmtstr[] = "Dirs:%-4ld Files:%-4ld Blocks:%-5ld Bytes:%-8ld\n";
- XBYTE TotHeaderMsg[] = "Totals:\n";
- XBYTE ColonStr[] = ":";
- XBYTE SlashStr[] = "/";
- XBYTE RamNameStr[] = "RAM:";
- X
- X/* ANSI color control strings */
- XBYTE penstr0[] = "\2330m"; /* Reset CON: */
- XBYTE penstr1[] = "\2330 p"; /* Cursor off */
- XBYTE penstr2[] = "\233 p"; /* Cursor on */
- XBYTE penstr3[] = "\23333m"; /* Color 3 NORM */
- XBYTE penstr4[] = "\2331;33;40m"; /* Color 3 BOLD */
- XBYTE penstr5[] = "\2331;31;40m"; /* Color 1 BOLD */
- X
- X/* CON: command sequence for window bounds report */
- XBYTE gwbrstr[4] = { 0x9b, '0', ' ', 'q' };
- X
- X/* Newline and "" source */
- XBYTE NLine[4] = { 10, 0, 0, 0 };
- X
- X/* Error messages */
- XBYTE BadOptFmtStr[] = "Unknown option: -%s\n";
- XBYTE ErrFmtStr[] = "LS: %s, Error #%ld\n";
- XBYTE NoExamFmtStr[] = "Cannot examine file or directory, Error #%ld\n";
- XBYTE NoFindFmtStr[] = "'%s' not found";
- XBYTE NoRAMMsg[] = "No RAM";
- XBYTE NoWildPathMsg[] = "Unable to pattern match paths";
- XBYTE VolEmptyMsg[] = "Volume or directory is empty.\n";
- XBYTE NoMatchMsg[] = "No match.\n";
- X
- X/* Pointers to usage strings for quick easy output */
- XBYTE *usagestrs[] =
- X{
- X Author, usage, usage0, usage1, usage2, usage3, usage4, usage5,
- X usage6, usage7, usage8, usage9, usage10, usage11, deffmtstr, usage12, 0L
- X};
- X
- XBYTE *thefmtstr = deffmtstr; /* Format string pointer for long output */
- XBYTE *curpath;
- XBYTE *theAntiPat; /* Avoid pattern string */
- X
- X/* Local CODE */
- XBYTE *GetDecNum __ARGS((BYTE *, LONG *));
- XLONG CmpDateBounds __ARGS((struct DateStamp *));
- XLONG GetFileDate __ARGS((BYTE *, struct DateStamp *));
- XLONG ParseCmdOptions __ARGS((LONG, LONG, BYTE **));
- Xstruct FibEntry *AllocFib __ARGS((VOID));
- Xstruct FibEntry *ModNextFib __ARGS((struct FibEntry *, LONG));
- Xstruct List *GetDir __ARGS((struct FileLock *, struct FileInfoBlock *));
- XVOID CleanUp __ARGS((BYTE *, LONG, LONG));
- XVOID DirIt __ARGS((struct FileLock *, BYTE *));
- XVOID FreeAllFibs __ARGS((struct List *));
- XVOID GetCLIArgs __ARGS((BYTE *, LONG *, BYTE **));
- XVOID LListDir __ARGS((struct List *));
- XVOID LListEntry __ARGS((struct FileInfoBlock *));
- XVOID LongList __ARGS((LONG *, LONG *, struct List *));
- XVOID PagePrompt __ARGS((LONG, LONG));
- XVOID ParseFormatOpts __ARGS((struct FileInfoBlock *));
- XVOID SetConPen __ARGS((BYTE *));
- XVOID SListDir __ARGS((struct List *));
- XVOID TestBreak __ARGS((VOID));
- XVOID Usage __ARGS((VOID));
- XVOID WCHR __ARGS((BYTE *));
- XVOID WSTR __ARGS((BYTE *));
- XVOID _main __ARGS((BYTE *));
- X
- X/* --------------------------------------------------------------------
- X * Allocate a FibEntry structure and associated FileInfoBlock.
- X * -------------------------------------------------------------------- */
- Xstruct FibEntry *AllocFib ()
- X{
- X struct FibEntry *tfibp;
- X
- X if ((tfibp = myalloc ((LONG)(sizeof (struct FibEntry) + sizeof (struct FileInfoBlock)))) != 0)
- X {
- X tfibp->fe_Fib = (struct FileInfoBlock *)((ULONG)tfibp + sizeof (struct FibEntry));
- X }
- X else
- X LSFlags |= BREAKFLAG;
- X return (tfibp);
- X}
- X
- X/* --------------------------------------------------------------------
- X * Use AmigaDOS to output a string to the stdout channel
- X * -------------------------------------------------------------------- */
- XVOID WSTR (tstring)
- X BYTE *tstring;
- X{
- X LONG i;
- X
- X i = strlen (tstring);
- X if (i > 0)
- X {
- X (VOID) Write ((BPTR)ConOut, tstring, i);
- X }
- X}
- X
- X/* --------------------------------------------------------------------
- X * Use AmigaDOS to put a character to the stdout
- X * -------------------------------------------------------------------- */
- XVOID WCHR (ch)
- X BYTE *ch;
- X{
- X (VOID) Write ((BPTR)ConOut, ch, 1L);
- X}
- X
- X/* --------------------------------------------------------------------
- X * Check to see if the user hit ^C
- X * -------------------------------------------------------------------- */
- XVOID TestBreak ()
- X{
- X ULONG oldsig;
- X
- X oldsig = SetSignal (0L, (LONG)SIGBREAKF_CTRL_C);
- X if ((oldsig & SIGBREAKF_CTRL_C) != 0)
- X {
- X WSTR ("\2330m\233 p**BREAK\n");
- X LSFlags |= BREAKFLAG;
- X }
- X}
- X
- X/* --------------------------------------------------------------------
- X * Prompt the user to hit return, wait till return is hit
- X * -------------------------------------------------------------------- */
- XVOID PagePrompt (page, maxpage)
- X LONG page, maxpage;
- X{
- X if (CurWinCols > maxnamlen && page > 1 && (LSFlags & NOINTERACT) == 0)
- X {
- X WSTR ("\2337m -- MORE -- ");
- X if (CurWinCols >= 27)
- X WSTR ("Press Return: ");
- X WSTR ("\2330m\233 p");
- X (VOID) Read ((BPTR)ConIn, workstr, 1L);
- X WSTR ("\2330 p\233F\233K");
- X TestBreak ();
- X }
- X
- X if ((LSFlags & (NOHEADERS|BREAKFLAG)) == 0)
- X {
- X if ((LSFlags & CONSOLE) != 0)
- X {
- X WSTR ("\2330 p\2334;33m");
- X }
- X (VOID) asprintf (workstr, "Page %ld of %ld:", page, maxpage);
- X WSTR (workstr);
- X SetConPen (penstr0);
- X WSTR (NLine);
- X }
- X}
- X
- X/* -------------------------------------------------------------------- */
- Xstruct FibEntry *ModNextFib(tfibp, rows)
- X struct FibEntry *tfibp;
- X LONG rows;
- X{
- X LONG i;
- X
- X for (i = 0; i < rows && tfibp->fe_Node.mln_Succ != 0; i++)
- X {
- X tfibp = (struct FibEntry *)tfibp->fe_Node.mln_Succ;
- X }
- X return(tfibp);
- X}
- X
- X/* --------------------------------------------------------------------
- X * set CON: character color to default Pen1 colors
- X * -------------------------------------------------------------------- */
- XVOID SetConPen (penstr)
- X BYTE *penstr;
- X{
- X if ((LSFlags & CONSOLE) != 0)
- X WSTR (penstr);
- X}
- X
- X/* #define DEBUGSLD 1 */
- X/* --------------------------------------------------------------------
- X * List a FibEntry list in a compact fashion
- X * -------------------------------------------------------------------- */
- XVOID SListDir (fibheadp)
- X struct List *fibheadp;
- X{
- X LONG avglen;
- X LONG colcnt;
- X LONG currow;
- X LONG dfcount;
- X LONG i, j, wlen;
- X LONG maxcol;
- X LONG maxpage;
- X LONG maxrow;
- X LONG maxwinrow;
- X LONG pagecnt;
- X LONG rowcnt;
- X LONG tlen;
- X LONG totlen;
- X struct FibEntry *hfibp, *tfibp;
- X
- X SetConPen (penstr1); /* Turn the cursor off since it will blink anyway */
- X GetWinBounds (&colcnt, &currow); /* Get current window size */
- X
- X if (CurWinCols == 0)
- X CurWinCols = colcnt;
- X if (CurWinRows == 0)
- X CurWinRows = currow;
- X
- X/* Make a average-case WxH estimate for # of display columns */
- X for (totlen = dfcount = 0, hfibp = (struct FibEntry *)fibheadp->lh_Head;
- X hfibp->fe_Node.mln_Succ != 0;
- X hfibp = (struct FibEntry *)hfibp->fe_Node.mln_Succ)
- X {
- X if (hfibp->fe_Fib->fib_DirEntryType > 0 && (LSFlags & CONSOLE) == 0)
- X (VOID) strcat (hfibp->fe_Fib->fib_FileName, SlashStr);
- X totlen += strlen (hfibp->fe_Fib->fib_FileName);
- X dfcount++;
- X }
- X
- X/* Calc average length of all entries */
- X avglen = totlen / dfcount; /* Avg name length = totlen/numentries */
- X if ((totlen % dfcount) != 0)
- X avglen++;
- X
- X if ((CurWinCols) <= maxnamlen) /* Longest name wider than window? */
- X maxcol = 1; /* Yep, just print one column */
- X else
- X {
- X /* Else maxcols = winwidth/namewidth */
- X for (maxcol = 0, colcnt = CurWinCols; colcnt >= avglen; maxcol++)
- X {
- X colcnt -= avglen + 2;
- X }
- X }
- X#ifdef DEBUGSLD
- X asprintf(workstr, "avg:%ld max:%ld\n", avglen, maxnamlen); WSTR(workstr);
- X#endif
- X
- X/* Dry run output avg-case WxH table to see if it needs adjusting */
- X for (;;)
- X {
- X /* Clear out previous padtab */
- X memset(padtab, 0, PADTABSIZE);
- X
- X /* Number of rows = total entries / entries per row */
- X maxrow = dfcount / maxcol;
- X if ((dfcount % maxcol) != 0) /* Round up if non-integral */
- X maxrow++;
- X#ifdef DEBUGSLD
- X asprintf(workstr, "avg: %ld rows by %ld cols\n", maxrow, maxcol); WSTR(workstr);
- X#endif
- X
- X for (rowcnt = 0, hfibp = (struct FibEntry *)fibheadp->lh_Head;
- X rowcnt < maxrow && hfibp->fe_Node.mln_Succ != 0;
- X rowcnt++, hfibp = (struct FibEntry *)hfibp->fe_Node.mln_Succ)
- X {
- X for (colcnt = 0, tfibp = hfibp;
- X colcnt < maxcol && tfibp->fe_Node.mln_Succ != 0;
- X colcnt++, tfibp = ModNextFib (tfibp, maxrow))
- X {
- X tlen = strlen (tfibp->fe_Fib->fib_FileName);
- X if (tlen > padtab[colcnt])
- X padtab[colcnt] = tlen;
- X }
- X
- X /* If this is the first row, calc actual maxcol/maxrow for this dfcount */
- X if (rowcnt == 0)
- X {
- X maxcol = colcnt;
- X maxrow = dfcount / maxcol;
- X if ((dfcount % maxcol) != 0) /* Round up if non-integral */
- X maxrow++;
- X }
- X }
- X
- X /* Calculate actual total width by adding up width of all columns */
- X for (colcnt = totlen = 0; (colcnt + 1) < maxcol; colcnt++)
- X {
- X totlen += (LONG)padtab[colcnt] + 2;
- X#ifdef DEBUGSLD
- X asprintf(workstr, "padtab[%ld]=%ld\n", colcnt, (LONG)padtab[colcnt]); WSTR(workstr);
- X#endif
- X }
- X totlen += (LONG)padtab[colcnt];
- X#ifdef DEBUGSLD
- X asprintf(workstr, "padtab[%ld]=%ld\n", colcnt, (LONG)padtab[colcnt]); WSTR(workstr);
- X asprintf(workstr, "totlen %ld\n", totlen); WSTR(workstr);
- X#endif
- X
- X /* if More than one column and
- X * total width of all columns is greater > our window width,
- X * then decrease number of display columns
- X */
- X if (maxcol > 1 && totlen > CurWinCols)
- X {
- X maxcol--;
- X#ifdef DEBUGSLD
- X asprintf(workstr, "new maxcol:%ld\n", maxcol); WSTR(workstr);
- X#endif
- X }
- X else
- X break;
- X }
- X#ifdef DEBUGSLD
- X asprintf(workstr, "adjusted: maxrow:%ld maxcol:%ld (winwidth:%ld totlen:%ld)\n", maxrow, maxcol, CurWinCols, totlen); WSTR(workstr);
- X#endif
- X
- X/* Calc number of pages */
- X maxwinrow = CurWinRows - 3;
- X if (maxwinrow <= 0)
- X maxwinrow = 1;
- X pagecnt = 1;
- X maxpage = maxrow / maxwinrow;
- X if ((maxrow % maxwinrow) != 0)
- X maxpage++;
- X
- X/* Do actual output scan */
- X for (rowcnt = 0, currow = maxwinrow, hfibp = (struct FibEntry *)fibheadp->lh_Head;
- X (LSFlags & BREAKFLAG) == 0 && rowcnt < maxrow && hfibp->fe_Node.mln_Succ != 0;
- X TestBreak(), rowcnt++, currow++, hfibp = (struct FibEntry *)hfibp->fe_Node.mln_Succ)
- X {
- X if (maxpage > 1 && currow == maxwinrow)
- X {
- X currow = 0;
- X if ((LSFlags & CONSOLE) != 0)
- X {
- X PagePrompt (pagecnt, maxpage);
- X if ((LSFlags & BREAKFLAG) != 0)
- X break;
- X }
- X pagecnt++;
- X }
- X
- X for (colcnt = 0, tfibp = hfibp;
- X colcnt < maxcol && tfibp->fe_Node.mln_Succ != 0;
- X colcnt++)
- X {
- X if (tfibp->fe_Fib->fib_DirEntryType < 0)
- X {
- X /* Print a file entry */
- X (VOID) stpcpy (workstr, tfibp->fe_Fib->fib_FileName);
- X wlen = strlen (workstr);
- X }
- X else
- X {
- X /* Print a directory entry */
- X workstr[0] = 0;
- X wlen = strlen (tfibp->fe_Fib->fib_FileName);
- X if ((LSFlags & CONSOLE) != 0)
- X (VOID) strcat (workstr, penstr3);
- X (VOID) strcat (workstr, tfibp->fe_Fib->fib_FileName);
- X if ((LSFlags & CONSOLE) != 0)
- X (VOID) strcat (workstr, penstr0);
- X }
- X
- X /* Move along list to the next entry, mod maxcol, print this entry */
- X tfibp = ModNextFib (tfibp, maxrow);
- X
- X /* If this is not the last column, pad with spaces till we get to next column */
- X if ((colcnt + 1) < maxcol && tfibp->fe_Node.mln_Succ != 0)
- X {
- X for (i = (LONG)padtab[colcnt] + 1, j = strlen (workstr); i >= wlen; i--, j++)
- X workstr[j] = ' ';
- X workstr[j] = 0;
- X }
- X /* Output the final entry */
- X WSTR (workstr);
- X }
- X
- X /* Filled this row, start next down */
- X WCHR (NLine);
- X }
- X
- X SetConPen (penstr2); /* Turn cursor back on */
- X}
- X
- X/* -------------------------------------------------------------------- */
- XBYTE *GetDecNum (cp, spccnt)
- X BYTE *cp;
- X LONG *spccnt;
- X{
- X for (*spccnt = 0; *cp >= '0' && *cp <= '9'; cp++)
- X {
- X *spccnt = *spccnt * 10 + (LONG)*cp - '0';
- X }
- X return (cp);
- X}
- X
- X/* -------------------------------------------------------------------- */
- XVOID ParseFormatOpts (fib)
- X struct FileInfoBlock *fib;
- X{
- X BYTE *cp1, *cp2, *reps;
- X BYTE *pathend, *thenamestr;
- X LONG i, spccnt;
- X
- X i = strlen (curpath);
- X pathend = curpath + i;
- X if (i > 1 && *(curpath + i - 1) != ':')
- X {
- X *(curpath + i) = '/';
- X i++;
- X *(curpath + i) = 0;
- X }
- X thenamestr = curpath + strlen(curpath);
- X cp2 = thenamestr;
- X if (fib->fib_DirEntryType > 0 && (LSFlags & CONSOLE) != 0)
- X cp2 = stpcpy (cp2, penstr3);
- X cp2 = stpcpy (cp2, fib->fib_FileName);
- X if (fib->fib_DirEntryType > 0 && (LSFlags & CONSOLE) != 0)
- X (VOID) stpcpy (cp2, penstr0);
- X
- X for (cp1 = workstr, cp2 = thefmtstr; *cp2 != 0; cp2++)
- X {
- X if (*cp2 != '%' && *cp2 != '\\')
- X *cp1++ = *cp2;
- X else
- X {
- X if (*cp2 == '%')
- X {
- X cp2++;
- X cp2 = GetDecNum (cp2, &spccnt);
- X if (spccnt > 99)
- X {
- X spccnt = 99;
- X }
- X
- X switch (*cp2)
- X {
- X case 'p':
- X reps = theprotstr;
- X break;
- X case 'd':
- X reps = thedatestr;
- X break;
- X case 't':
- X reps = thetimestr;
- X break;
- X case 'b':
- X reps = theblksstr;
- X break;
- X case 's':
- X reps = thesizestr;
- X break;
- X case 'n':
- X if (fib->fib_DirEntryType > 0 && (LSFlags & CONSOLE) != 0 && spccnt > 0)
- X spccnt += 7;
- X if ((LSFlags & FULLPATHNAMES) != 0)
- X reps = curpath;
- X else
- X reps = thenamestr;
- X break;
- X case '%':
- X *cp1++ = '%';
- X *cp1++ = 0;
- X default:
- X reps = &NLine[1];
- X break;
- X }
- X for (i = strlen(reps); i < spccnt; i++)
- X *cp1++ = ' ';
- X cp1 = stpcpy (cp1, reps);
- X }
- X else
- X {
- X cp2++;
- X switch (*cp2)
- X {
- X case 'n':
- X *cp1++ = '\n';
- X break;
- X case 't':
- X *cp1++ = '\t';
- X break;
- X case '\\':
- X *cp1++ = '\\';
- X break;
- X default:
- X break;
- X }
- X *cp1 = 0;
- X }
- X }
- X }
- X WSTR (workstr);
- X
- X if ((LSFlags & NOTEFLAG) != 0 && fib->fib_Comment[0] != 0)
- X {
- X SetConPen(penstr3);
- X (VOID)asprintf(workstr, "/* %s */\n", fib->fib_Comment);
- X WSTR (workstr);
- X SetConPen(penstr0);
- X }
- X *pathend = 0;
- X}
- X
- X/* --------------------------------------------------------------------
- X * Verbosely list a particular FibEntry
- X * -------------------------------------------------------------------- */
- XVOID LListEntry (fib)
- X struct FileInfoBlock *fib;
- X{
- X LONG i, pmodes;
- X
- X pmodes = fib->fib_Protection & 0xff;
- X (VOID)stpcpy (theprotstr, "chsparwed");
- X for (i = 3; i >= 0; i--)
- X {
- X if ((pmodes & (1 << i)) != 0)
- X theprotstr[8 - i] = '-';
- X if ((pmodes & (1 << (i + 4))) == 0)
- X theprotstr[4 - i] = '-';
- X }
- X
- X if (fib->fib_Comment[0] == 0)
- X theprotstr[0] = '-';
- X
- X FibFileDate (&fib->fib_Date, thedatestr, thetimestr);
- X
- X if (fib->fib_DirEntryType > 0)
- X {
- X (VOID)stpcpy (theblksstr, "0");
- X (VOID)stpcpy (thesizestr, "Dir");
- X }
- X else
- X {
- X (VOID) asprintf (theblksstr, LongFmtStr, fib->fib_NumBlocks);
- X (VOID) asprintf (thesizestr, LongFmtStr, fib->fib_Size);
- X }
- X
- X ParseFormatOpts (fib);
- X}
- X
- X/* --------------------------------------------------------------------
- X * List a directory in a verbose informative manner
- X * -------------------------------------------------------------------- */
- XVOID LListDir (fibheadp)
- X struct List *fibheadp;
- X{
- X struct FibEntry *tfibp;
- X
- X SetConPen(penstr1);
- X
- X totblocks = totbytes = 0;
- X for (tfibp = (struct FibEntry *)fibheadp->lh_Head;
- X tfibp->fe_Node.mln_Succ != 0;
- X tfibp = (struct FibEntry *)tfibp->fe_Node.mln_Succ)
- X {
- X TestBreak();
- X if ((LSFlags & BREAKFLAG) != 0)
- X return;
- X LListEntry (tfibp->fe_Fib);
- X if (tfibp->fe_Fib->fib_DirEntryType < 0)
- X {
- X totblocks += tfibp->fe_Fib->fib_NumBlocks;
- X totbytes += tfibp->fe_Fib->fib_Size;
- X }
- X }
- X
- X if ((LSFlags & (BREAKFLAG | NOHEADERS)) == 0)
- X {
- X (VOID) asprintf (workstr, totalfmtstr, dircount, filecount, totblocks, totbytes);
- X WSTR (workstr);
- X }
- X
- X SetConPen(penstr2);
- X}
- X
- X/* -------------------------------------------------------------------- */
- XLONG CmpDateBounds (tdate)
- X struct DateStamp *tdate;
- X{
- X if ((LSFlags & SHOWNEWERTHAN) != 0)
- X {
- X if (CompareDateStamps(&thenewdate, tdate) >= 0)
- X return (0L);
- X }
- X if ((LSFlags & SHOWOLDERTHAN) != 0)
- X {
- X if (CompareDateStamps(tdate, &theolddate) >= 0)
- X return (0L);
- X }
- X return (1L);
- X}
- X
- X/* --------------------------------------------------------------------
- X * Free up memory allocated to a linked list of FibEntrys
- X * -------------------------------------------------------------------- */
- XVOID FreeAllFibs (fibheadp)
- X struct List *fibheadp;
- X{
- X struct FibEntry *tfibp;
- X
- X if (fibheadp != 0)
- X {
- X while (fibheadp->lh_Head->ln_Succ != 0)
- X {
- X tfibp = (struct FibEntry *)RemTail(fibheadp);
- X myfree (tfibp);
- X }
- X
- X /* Now free the MinList itself */
- X myfree (fibheadp);
- X }
- X}
- X
- X/* --------------------------------------------------------------------
- X * Allocate and fill a linked list of FileInfoBlocks
- X * -------------------------------------------------------------------- */
- Xstruct List *GetDir (lockp, fibp)
- X struct FileLock *lockp;
- X struct FileInfoBlock *fibp;
- X{
- X BYTE *thepat; /* Pattern pointer to dir or file pattern */
- X LONG matchstat; /* Result of wildmatch() */
- X LONG nextstat; /* Status of ExNext() */
- X LONG tempnamlen; /* Compare length for strings */
- X LONG dfcount;
- X struct List *fibhead; /* Temp list of Fibs created */
- X struct List *dirhead; /* Temp list of dirs if SHOWDIRS == 0 */
- X
- X maxnamlen = dfcount = dircount = filecount = 0L;
- X
- X/* Initialize an exec list of nodes, zero entries */
- X if ((fibhead = myalloc ((LONG)sizeof(struct MinList))) == 0)
- X return (0L);
- X NewList (fibhead);
- X
- X/* Allocate an separate list for directories that don't match specs */
- X if ((dirhead = myalloc((LONG)sizeof(struct MinList))) == 0)
- X goto BADALLOC;
- X NewList (dirhead);
- X
- X do
- X {
- X TestBreak ();
- X if ((LSFlags & BREAKFLAG) != 0)
- X goto GOODRET;
- X
- X /* If we got something */
- X if ((nextstat = ExNext ((BPTR)lockp, fibp)) != 0)
- X {
- X dfcount++;
- X
- X /* If the entry is wanted bump count of files or directories */
- X if (CmpDateBounds (&fibp->fib_Date) != 0)
- X {
- X if (fibp->fib_DirEntryType > 0) /* It's a directory */
- X thepat = theDirPat;
- X else
- X thepat = theFilePat;
- X
- X matchstat = wildmatch (fibp->fib_FileName, thepat);
- X if ((LSFlags & ANTIMATCH) != 0 && matchstat != 0)
- X matchstat = wildmatch (fibp->fib_FileName, theAntiPat) ^ 1;
- X
- X if (matchstat == 0) /* No match? Then move on */
- X continue;
- X
- X if (fibp->fib_DirEntryType > 0) /* It's a directory */
- X {
- X if (FillFibEntry (dirhead, fibp) == 0)
- X goto BADALLOC;
- X if ((LSFlags & SHOWDIRS) != 0)
- X {
- X dircount++;
- X gdircount++;
- X }
- X else
- X continue;
- X }
- X else /* It's a file entry */
- X {
- X if ((LSFlags & SHOWFILES) != 0)
- X {
- X filecount++;
- X gfilecount++;
- X gtotblocks += fibp->fib_NumBlocks;
- X gtotbytes += fibp->fib_Size;
- X }
- X else /* Don't want this file, move on to next entry */
- X continue;
- X }
- X
- X /* See if this is the longest filename for later use in listing */
- X tempnamlen = strlen (fibp->fib_FileName);
- X if (tempnamlen > maxnamlen)
- X maxnamlen = tempnamlen;
- X
- X /* Allocate another FibEntry, put the info inside */
- X if (FillFibEntry (fibhead, fibp) == 0)
- X goto BADALLOC;
- X }
- X }
- X } while (nextstat != 0);
- X
- X/* No entries found? print message and return FALSE */
- X if ((dircount + filecount) == 0)
- X {
- X if ((LSFlags & NOHEADERS) == 0)
- X {
- X if (dfcount == 0)
- X WSTR (VolEmptyMsg);
- X else
- X WSTR (NoMatchMsg);
- X }
- X }
- X else
- X {
- X if ((LSFlags & (SHOWDIRS|SHOWFILES)) != 0)
- X {
- X if ((LSFlags & LONGLIST) == 0) /* Short listing wanted */
- X SListDir (fibhead);
- X else /* Full listing */
- X LListDir (fibhead);
- X }
- X }
- X
- XGOODRET:
- X FreeAllFibs (fibhead);
- X return (dirhead);
- X
- XBADALLOC:
- X FreeAllFibs (fibhead);
- X FreeAllFibs (dirhead);
- X return (0L);
- X}
- X
- X/* --------------------------------------------------------------------
- X * Given a directory name and a lock on that directory, create a list
- X * of entries. Recursively decends into subdirectories if flaged.
- X * -------------------------------------------------------------------- */
- XVOID DirIt (curlock, dirname)
- X struct FileLock *curlock;
- X BYTE *dirname;
- X{
- X BYTE *subdir;
- X LONG dnamlen;
- X struct FibEntry *tfibp;
- X struct FileLock *sublock;
- X struct List *fibheadp;
- X
- X/* Try to fill FileInfoBlock, bomb if not readable for some reason */
- X if (Examine ((BPTR)curlock, GFibp) == 0)
- X {
- X (VOID) asprintf (workstr, NoExamFmtStr, IoErr());
- X WSTR (workstr);
- X return;
- X }
- X
- X/* Put directory header for each listing, if we know the name && recursive */
- X if (dirname[0] != 0 && (LSFlags & LISTALL) != 0 && (LSFlags & NOHEADERS) == 0)
- X {
- X if ((LSFlags & CONSOLE) != 0)
- X (VOID)asprintf (workstr, "\23330;41m %s \2330m\n", dirname);
- X else
- X (VOID)asprintf (workstr, "%s\n", dirname);
- X WSTR (workstr);
- X }
- X
- X/* If this is a single file list it verbosely */
- X if (GFibp->fib_DirEntryType < 0)
- X {
- X if ((LSFlags & SHOWFILES) != 0)
- X {
- X (VOID) GetPathString (thePath, thePath);
- X LListEntry (GFibp);
- X }
- X }
- X else /* It is a directory entry */
- X {
- X /* Allocate, fill, and display a dir of entries, check for no ram or abort */
- X if ((fibheadp = GetDir (curlock, GFibp)) != 0)
- X {
- X /* Recursively descend any subdirs in this list, if wanted */
- X if ((LSFlags & LISTALL) != 0)
- X {
- X for (tfibp = (struct FibEntry *)fibheadp->lh_Head;
- X tfibp->fe_Node.mln_Succ != 0;
- X tfibp = (struct FibEntry *)tfibp->fe_Node.mln_Succ)
- X {
- X TestBreak ();
- X if ((LSFlags & BREAKFLAG) != 0)
- X break;
- X
- X if (tfibp->fe_Fib->fib_DirEntryType > 0)
- X {
- X /* Alloc length of path + 1 + newdir name +1 + length of maxname + 1 for NULL
- X * + 1 for null + 3 for rounding.
- X */
- X dnamlen = (LONG)(strlen (dirname) + strlen (tfibp->fe_Fib->fib_FileName) + 36);
- X if ((subdir = myalloc ((LONG)dnamlen)) != 0)
- X {
- X if (dirname[0] != 0)
- X {
- X (VOID) stpcpy (subdir, dirname);
- X dnamlen = strlen (dirname) - 1;
- X if (dirname[dnamlen] != ':' && dirname[dnamlen] != '/')
- X {
- X (VOID) strcat (subdir, SlashStr);
- X }
- X }
- X (VOID) strcat (subdir, tfibp->fe_Fib->fib_FileName);
- X
- X if ((sublock = (struct FileLock *)Lock (subdir, (LONG)ACCESS_READ)) != 0)
- X {
- X if ((LSFlags & NOHEADERS) == 0)
- X WCHR (NLine); /* Put a blank line between directories */
- X
- X curpath = subdir;
- X
- X DirIt (sublock, subdir); /* Recurse into this subdirectory */
- X
- X UnLock ((BPTR)sublock); /* Unlock our sublock */
- X }
- X myfree (subdir); /* Free the current namespace */
- X }
- X }
- X }
- X }
- X /* Free up this fib list */
- X FreeAllFibs (fibheadp);
- X }
- X }
- X}
- X
- X/* -------------------------------------------------------------------- */
- XVOID GetCLIArgs (line, argc, argv)
- X BYTE *line;
- X LONG *argc;
- X BYTE **argv;
- X{
- X BYTE **pargv, *qarg;
- X
- X *argc = 0;
- X while (*argc < MAXARG)
- X {
- X while (*line == ' ' || *line == '\t' || *line == '\n')
- X line++;
- X if (*line == 0)
- X break;
- X pargv = &argv[*argc];
- X *argc += 1;
- X
- X if (*line == '"')
- X {
- X qarg = line;
- X line += 1;
- X *pargv = line; /* ptr inside quoted string */
- X while (*line != 0 && *line != '"')
- X line++;
- X if (*line == 0) /* Hit end of string without quote! */
- X {
- X *pargv = qarg; /* Must be okay */
- X break;
- X }
- X else
- X *line++ = 0; /* terminate arg ontopof quote */
- X }
- X else /* non-quoted arg */
- X {
- X *pargv = line;
- X while (*line != 0 && !(*line == ' ' || *line == '\t' || *line == '\n'))
- X line++;
- X if (*line == 0)
- X break;
- X else
- X *line++ = 0; /* terminate arg */
- X }
- X } /* while */
- X}
- X
- X/* -------------------------------------------------------------------- */
- XLONG GetFileDate(name, ptime)
- X char *name;
- X struct DateStamp *ptime;
- X{
- X LONG status;
- X struct FileLock *flock;
- X struct FileInfoBlock *fib;
- X
- X status = 0;
- X if ((fib = myalloc ((LONG)sizeof(struct FileInfoBlock))) != 0)
- X {
- X if ((flock = (struct FileLock *)Lock (name, (LONG)ACCESS_READ)) != 0)
- X {
- X if (Examine ((BPTR)flock, fib) != 0)
- X {
- X *ptime = fib->fib_Date; /* Copy the Date structure */
- X status = 1;
- X }
- X UnLock ((BPTR)flock);
- X }
- X myfree (fib);
- X }
- X return (status);
- X}
- X
- X/* --------------------------------------------------------------------
- X * Deallocate and close everything
- X * -------------------------------------------------------------------- */
- XVOID CleanUp (exit_msg, exit_status, result2)
- X BYTE *exit_msg;
- X LONG exit_status, result2;
- X{
- X BYTE workstr[WORKSIZE];
- X struct Process *procp;
- X
- X/* Make sure we unlock any locks we created! */
- X if (CurFLock != 0 && (LSFlags & PATHNAMED) != 0)
- X UnLock ((BPTR)CurFLock);
- X
- X/* Free our fib */
- X myfree (GFibp);
- X
- X if (*exit_msg != 0)
- X {
- X (VOID) asprintf (workstr, ErrFmtStr, exit_msg, result2);
- X WSTR (workstr);
- X }
- X
- X/* Put windowptr back */
- X procp = (struct Process *) FindTask (0L);
- X procp->pr_WindowPtr = OldWindowPtr;
- X
- X/* Set return status, exit */
- X procp->pr_Result2 = result2;
- X exit ((int)exit_status);
- X}
- X
- X/* --------------------------------------------------------------------
- X * Explain how to use.
- X * -------------------------------------------------------------------- */
- XVOID Usage ()
- X{
- X LONG i;
- X
- X for (i = 0; usagestrs[i] != 0; i++)
- X WSTR (usagestrs[i]);
- X CleanUp (&NLine[1], 20L, 120L);
- X}
- X
- X/* -------------------------------------------------------------------- */
- XLONG ParseCmdOptions (ncnt, argc, argv)
- X LONG ncnt, argc;
- X BYTE **argv;
- X{
- X BYTE tmpmsg[4];
- X LONG i, cnt, len;
- X struct Process *procp;
- X
- X cnt = ncnt; /* Current arg number that contains the options */
- X ncnt += 1; /* Advance to next arg */
- X
- X for (i = 1, len = strlen (argv[cnt]); i < len; i++)
- X {
- X switch (argv[cnt][i])
- X {
- X case '?':
- X case 'h':
- X Usage ();
- X break;
- X case 'D':
- X LSFlags |= FILESFIRST;
- X break;
- X case 'F':
- X if (argc < (ncnt + 1)) /* Missing required format string */
- X Usage ();
- X thefmtstr = argv[ncnt]; /* Else our format string is the next arg */
- X ncnt += 1; /* Bump arg counter */
- X LSFlags |= LONGLIST;
- X break;
- X case 'H':
- X LSFlags |= NOHEADERS;
- X break;
- X case 'I':
- X LSFlags |= NOINTERACT;
- X break;
- X case 'M':
- X LSFlags |= MIXFILESDIRS;
- X break;
- X case 'N':
- X if (argc < (ncnt + 1)) /* Missing required name string */
- X Usage ();
- X else
- X {
- X if (GetFileDate (argv[ncnt], &thenewdate) == 0)
- X NoFileExit (argv[ncnt]);
- X ncnt += 1; /* Bump arg counter */
- X LSFlags |= SHOWNEWERTHAN;
- X }
- X break;
- X case 'O':
- X if (argc < (ncnt + 1)) /* Missing required name string */
- X {
- X Usage ();
- X }
- X else
- X {
- X if (GetFileDate (argv[ncnt], &theolddate) == 0)
- X NoFileExit (argv[ncnt]);
- X ncnt += 1; /* Bump arg counter */
- X LSFlags |= SHOWOLDERTHAN;
- X }
- X break;
- X case 'P':
- X LSFlags |= (FULLPATHNAMES | LONGLIST);
- X break;
- X case 'R':
- X LSFlags |= LISTALL;
- X break;
- X case 'T':
- X LSFlags |= TOTALIZE;
- X break;
- X case 'X':
- X if (argc < (ncnt + 1)) /* Missing required width number */
- X {
- X Usage ();
- X }
- X else
- X {
- X (VOID) GetDecNum (argv[ncnt], &CurWinCols);
- X ncnt += 1; /* Bump arg counter */
- X }
- X break;
- X case 'Y':
- X if (argc < (ncnt + 1)) /* Missing required height number */
- X {
- X Usage ();
- X }
- X else
- X {
- X (VOID) GetDecNum (argv[ncnt], &CurWinRows);
- X ncnt += 1; /* Bump arg counter */
- X }
- X break;
- X case 'c':
- X LSFlags |= LONGLIST | NOTEFLAG;
- X break;
- X case 'd':
- X LSFlags &= ~SHOWFILES;
- X break;
- X case 'f':
- X LSFlags &= ~SHOWDIRS;
- X break;
- X case 'k':
- X LSFlags &= ~CONSOLE;
- X break;
- X case 'l':
- X LSFlags |= LONGLIST;
- X break;
- X case 'n':
- X LSFlags |= NOSORTFLAG;
- X break;
- X case 'p':
- X procp = (struct Process *) FindTask (0L);
- X procp->pr_WindowPtr = OldWindowPtr;
- X break;
- X case 'r':
- X LSFlags |= REVFLAG;
- X break;
- X case 's':
- X sortkey = 1;
- X break;
- X case 't':
- X sortkey = 2;
- X break;
- X case 'v':
- X if (argc < (ncnt + 1)) /* Missing required pattern string */
- X Usage ();
- X theAntiPat = argv[ncnt]; /* Point to pattern area */
- X ncnt += 1; /* Skip over arg */
- X LSFlags |= ANTIMATCH; /* Set flag to use antipat */
- X break;
- X default:
- X tmpmsg[0] = argv[cnt][i];
- X tmpmsg[1] = 0;
- X (VOID) asprintf (workstr, BadOptFmtStr, tmpmsg);
- X WSTR (workstr);
- X Usage ();
- X break;
- X }
- X }
- X return(ncnt);
- X}
- X
- X/* -------------------------------------------------------------------- */
- XVOID _main (line)
- X BYTE *line;
- X{
- X BYTE *argv[MAXARG]; /* arg pointers */
- X LONG argc; /* arg count */
- X LONG cnt;
- X struct Process *procp;
- X
- X/* Prevent system request from occuring by default */
- X procp = (struct Process *) FindTask (0L);
- X OldWindowPtr = procp->pr_WindowPtr;
- X procp->pr_WindowPtr = (APTR)-1L;
- X
- X/* Construct list of args */
- X GetCLIArgs (line, &argc, argv);
- X
- X/* Grab FileHandles for input and output to console (or redirection file) */
- X ConIn = (struct FileHandle *)Input ();
- X ConOut = (struct FileHandle *)Output ();
- X
- X/* Is this a CLI? Set a flag */
- X if (IsInteractive ((BPTR)ConOut) != 0 && IsInteractive ((BPTR)ConIn) != 0)
- X LSFlags |= CONSOLE;
- X
- X/* Allocate a global FileInfoBlock for ExNext() */
- X if ((GFibp = myalloc ((LONG) sizeof (struct FileInfoBlock))) == 0)
- X NoMemExit ();
- X
- X/* Initialize arg count, zero grand totals */
- X cnt = 1;
- X gtotblocks = gtotbytes = gdircount = gfilecount = 0;
- X
- X/* Parse command line arguments, if any */
- X do
- X {
- X if (cnt < argc && argv[cnt][0] == '-')
- X {
- X /* Reset for next arg */
- X LSFlags &= CONSOLE;
- X LSFlags |= SHOWDIRS | SHOWFILES;
- X thefmtstr = deffmtstr;
- X
- X do
- X {
- X cnt = ParseCmdOptions(cnt, argc, argv);
- X } while (cnt < argc && argv[cnt][0] == '-');
- X }
- X
- X /* Is there an named path arg to do? */
- X if (cnt < argc)
- X {
- X LSFlags |= PATHNAMED; /* Flag that we have a name */
- X theFilePat[0] = 0; /* Terminate pattern strings */
- X theDirPat[0] = 0;
- X (VOID) stpcpy (thePath, argv[cnt]); /* Copy this arg to work space */
- X cnt++; /* Advance arg counter */
- X
- X /* Wild pathname? Separate into components until we find a non-wild path */
- X if (iswild (thePath) != 0)
- X {
- X (VOID) GetFileString (theFilePat, thePath);
- X (VOID) stpcpy (theDirPat, theFilePat);
- X (VOID) GetPathString (thePath, thePath);
- X
- X /* Still wild? First part must be wild filename to match */
- X if (iswild (thePath) != 0)
- X {
- X (VOID) GetFileString (theDirPat, thePath);
- X (VOID) GetPathString (thePath, thePath);
- X }
- X }
- X#ifdef DEBUGIT
- X asprintf(workstr, "path: %s\n", thePath); WSTR (workstr);
- X asprintf(workstr, " dir: %s\n", theDirPat); WSTR (workstr);
- X asprintf(workstr, "file: %s\n", theFilePat); WSTR (workstr);
- X#endif
- X
- X /* No wildcards allowed in the final pathname! */
- X if (iswild (thePath) != 0)
- X CleanUp (NoWildPathMsg, 20L, 120L);
- X
- X /* Now try to lock the dir (or file) */
- X if ((CurFLock = (struct FileLock *)Lock (thePath, (LONG)ACCESS_READ)) == 0)
- X {
- X NoFileExit (thePath);
- X }
- X }
- X else
- X {
- X /*
- X * If no filename was specified, steal Lock on current directory from
- X * CLI process task info. We durn well better get something useful back;
- X * since we don't do any error checking on the "borrowed" Lock.
- X */
- X CurFLock = (struct FileLock *)procp->pr_CurrentDir;
- X }
- X
- X /* Make a full pathname string from given CurFLock if no colon in path */
- X if (aindex(thePath, ':') == 0)
- X MakePathString (CurFLock, thePath);
- X curpath = thePath;
- X
- X#ifdef DEBUGIT
- X asprintf(workstr, "Final path: %s\n", thePath); WSTR (workstr);
- X#endif
- X
- X /* If there isn't a dir pattern or file pattern specified, match everything */
- X if (theDirPat[0] == 0)
- X {
- X theDirPat[0] = '*'; /* "*" default matchall dir pattern */
- X theDirPat[1] = 0; /* Null terminate string */
- X }
- X
- X if (theFilePat[0] == 0)
- X {
- X theFilePat[0] = '*';
- X theFilePat[1] = 0;
- X }
- X
- X /* Get the directory for this path, display it */
- X DirIt (CurFLock, thePath);
- X
- X /* Release the lock if we locked it */
- X if (CurFLock != 0 && (LSFlags & PATHNAMED) != 0)
- X {
- X UnLock ((BPTR)CurFLock);
- X }
- X CurFLock = 0;
- X
- X /* Still more args? Put a linefeed between listing outputs
- X if (cnt < argc && (LSFlags & NOHEADERS) == 0)
- X WCHR (NLine);
- X */
- X TestBreak();
- X if ((LSFlags & TOTALIZE) != 0)
- X {
- X SetConPen (penstr4);
- X WSTR (TotHeaderMsg);
- X SetConPen (penstr5);
- X (VOID) asprintf (workstr, totalfmtstr, gdircount, gfilecount, gtotblocks, gtotbytes);
- X WSTR (workstr);
- X SetConPen (penstr0);
- X }
- X } while (cnt < argc && (LSFlags & BREAKFLAG) == 0);
- X
- X/* All done! Clean exit */
- X CleanUp (&NLine[1], 0L, 0L);
- X}
- END_OF_FILE
- if test 43452 -ne `wc -c <'src/ls.c'`; then
- echo shar: \"'src/ls.c'\" unpacked with wrong size!
- fi
- # end of 'src/ls.c'
- fi
- echo shar: End of archive 3 \(of 3\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 3 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
- Mail comments to the moderator at <amiga-request@cs.odu.edu>.
- Post requests for sources, and general discussion to comp.sys.amiga.
-